package cz.pecinovsky.česky.oopnz._134_;
//Příliš žluťoučký kůň úpěl ďábelské ódy

import cz.pecinovsky.česky.oopnz.správce.Řadič;
import cz.pecinovsky.česky.oopnz.správce.SprávcePlátna;

//import cz.pecinovsky.česky.oopnz.utility.IO;


import static cz.pecinovsky.česky.oopnz._134_.IZávod_138_       .IZávod;
import static cz.pecinovsky.česky.oopnz._134_.IZávodník_137_    .IZávodník;
import static cz.pecinovsky.česky.oopnz._134_.Okruh_134_        .Okruh;
import static cz.pecinovsky.česky.oopnz._134_.PoleCesty_134_    .PoleCesty;
import static cz.pecinovsky.česky.oopnz._134_.Šipka_134_        .Šipka;
import static cz.pecinovsky.česky.oopnz._134_.Vozidlo_B_137_    .Vozidlo_B;


import static cz.pecinovsky.česky.oopnz._134_.Závod_137_        .Závod;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ Konec ignorovaného počátečního textu +++++
//%I+
//
//import cz.pecinovsky.česky.oopnz.správceplátna.IOvládaný;
//import cz.pecinovsky.česky.oopnz.správceplátna.Řadič;
//import cz.pecinovsky.česky.oopnz.správceplátna.SprávcePlátna;
//%I-

import cz.pecinovsky.česky.oopnz.utility.Barva;
import cz.pecinovsky.česky.oopnz.utility.IO;
import cz.pecinovsky.česky.oopnz.utility.Pozice;
import cz.pecinovsky.česky.oopnz.utility.Směr8;
//%X+ xxxxx Začátek přeskakovaného textu xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class Závod_137_
{    private Závod_137_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- Konec přeskakovaného textu -----


/*******************************************************************************
 * Instance třídy {@code Závod} představují závody, které je možno absolvovat.
 * Závod je charakterizován okruhem, na kterém se pojede.
 * Postupně se k němu mohou hlásit závodníci.
 * Vždy, když jeden závodník závod dokončí, může se přihlásit další.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
//%I+ <138
//public class Závod
//%I-
//%A+ >138
public class Závod implements IZávod
//%A-
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Plátno, na které se bude instance kreslit. */
    private static final SprávcePlátna SP = SprávcePlátna.getInstance();



//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Okruh, na němž je závoděno. */
    private final Okruh okruh;

    /** Pole, z nějž závod odstartuje. */
    private final PoleCesty start;



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Kontrolovaný závodník, který se snaží co nejrychleji objet okruh. */
    private IZávodník závodník;

    /** Řadič, zprostředkovávající ovládání závodníka z klávesnice. */
    private Řadič řadič;

    /** Příští pole, na které má závodník dojet a na němž se bude kontrolovat,
     *  zda je skutečně projel.  */
    private PoleCesty cíl;

    /** Systémový čas v okamžiku startu závodu. */
    private long čas0;



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří instanci schopnou pořádat závody na zadaném okruhu.
     *
     * @param okruh Okruh, na němž se budou pořádat závody
     */
    public Závod(Okruh okruh)
    {
        this.okruh    = okruh;
        this.start    = okruh.getPočátek();
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Zaregistruje zadaného závodníka, umístí jej na start závodu
     * a přihlásí jej jako posluchače klávesnice.
     *
     * @param závodník Závodník registrující se pro daný závod
     */
//%A+ >138
    @Override
//%A-
    public void registrace(IZávodník závodník)
    {
        if (this.závodník != null) {
            IO.zpráva("U tohoto závodu je již registrován \n" + this.závodník +
                  "\n\nMusíte se svojí registrací počkat, až dojede do cíle.");
            return;                         //==========>
        }
        Pozice pozice = start.getPozice();
        int    modul  = start.getModul();
        Směr8  směr   = start.getSměr();

        závodník.setPozice(pozice);
        závodník.setModul(modul);
        závodník.setSměr(směr);

        this.řadič    = new Řadič(závodník);
        this.cíl      = start.getDalší();
        this.závodník = závodník;
        this.čas0     = System.currentTimeMillis();
    }


    /***************************************************************************
     * Prověří, že závodník dojel do správné průběžné cílové pozice.
     * Pokud dojel, připraví další průběžnou pozici, pokud nedojel, čeká dál.
     *
     * @param závodník Závodník hlásící změnu své pozice
     */
//%A+ >138
    @Override
//%A-
    public void průjezdníKontrola(IZávodník závodník)
    {
        //Testuji, zda se jedná o tutéž instanci, proto operátor !=
        if (this.závodník != závodník) {
            return;                      //==========>
        }
        Pozice pz = závodník.getPozice();
        Pozice pc = cíl     .getPozice();
        if (pz.equals(pc)) {
            if (cíl.equals(start)) {
                konecZávodu(závodník);
                return;                  //==========>
            }
            cíl = cíl.getDalší();
        }
    }


    /***************************************************************************
     * Vrátí řetězec sloužící jako textový "podpis" instance
     * používaný především při ladění.
     */
    @Override
    public String toString()
    {
        return "Závod_(okruh=" + okruh + ", závodník=" + závodník + ")";
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Ukončí závod pro zadaného závodníka.
     *
     * @param závodník Závodník ukončivší závod
     */
    private void konecZávodu(IZávodník závodník)
    {
        //Testuji, zda se jedná o tutéž instanci, proto operátor !=
        if (this.závodník != závodník) {
            return;                      //==========>
        }
        long nyní = System.currentTimeMillis();
        this.řadič.konec();
        this.závodník = null;
        int čas = (int)(nyní - čas0 + 50) / 100;
        System.out.println("\n\nZávodík " + závodník.getNázev() +
               " absolvoval okruh v čase " + čas/10 + "," + čas%10 + " sekund");
    }



//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTY A METODA MAIN =======================================================

    /***************************************************************************
     * Testovací metoda.
     */
    public static void test()
    {
        Šipka  šipka = new Šipka(0, 0, Barva.BÍLÁ);
        Vozidlo_B vb = new Vozidlo_B(šipka);

        //Okruh, který se pojede, lze vybrat zakomentováním, resp.
        //odkomentováním řádku s tím správným okruhem
        Závod  závod = new Závod(
//                                  Okruh.elko(new Pozice(0,0), Barva.HNĚDÁ));
                                  Okruh.čtverec(new Pozice(50,50)));
        vb.setNázev("Závodník");
        vb.registrujSePro(závod);
    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}

//%%-  ----- Začátek ignorovaného závěrečného textu -----
////////////////////////////////////////////////////////////////////////////////
//== TESTY A METODA MAIN =======================================================

    /***************************************************************************
     * Testovací metoda.
     */
    public static void test()
    {
        Závod.test();

//        IO.zpráva("Až se pokocháš, stiskni OK");
//        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main( String[] args )  {  test();  }
}
